package sweet.helper.mail

import sweet.helper._


/**
 * A simple EmailSender implemenation that supports basic smtp, or SSL enabled smtp like gmail
 * server. The typical smtp port is 25, while SSL port is 465.
 */
class EmailSender(val host: String, val port: Int, val defaultFrom: String, 
  val sslEnabled: Boolean, val user: String , val password: String) extends Logger{
      
  import javax.mail._
  import javax.mail.internet._
  import org.apache.commons.lang.StringUtils
  
  val userPassAuthenticator = new Authenticator() {
		override def getPasswordAuthentication: PasswordAuthentication = new PasswordAuthentication(user, password)
	}
  
  val props = {
    val p = JProperties(
      "mail.host" -> host,
      "mail.from" -> defaultFrom,
      "mail.transport.protocol" -> "smtp", 
      "mail.smtp.port"->(""+port),
      "mail.smtp.auth"->"false"
    )
    if(sslEnabled){      
      p.setProperty("mail.smtp.socketFactory.port", (""+port));
      p.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
      p.setProperty("mail.smtp.socketFactory.fallback", "false");
    }
    if(StringUtils.isNotBlank(user)){
      p.setProperty("mail.smtp.auth", "true");
    }
    p
  }
  
  def this(host: String, defaultFrom: String) = this(host, 25, defaultFrom, false, "", "")
  def this(host: String) = this(host, 25, "admin@localhost", false, "", "")
  def this() = this("localhost", "admin@localhost")
  
  /** Send an email with defaultFrom address. */
  def send(to: String, subj: String, msg: String){
    send(defaultFrom, to, subj, msg)
  }
  
  /** Send an email. */
  def send(from: String, to: String, subj: String, msg: String){
    logger.info("Send email to "+to)
    logger.debug("Subj: "+subj)
    logger.debug("Msg: "+msg)
    
    //Create a session based on auth or not.
    val sess = 
      if(StringUtils.isNotBlank(user)) Session.getDefaultInstance(props, userPassAuthenticator)
      else Session.getDefaultInstance(props)
      
    //Send msg using transport.
    val message = new MimeMessage(sess)
    message.setFrom(new InternetAddress(from))
    message.addRecipients(Message.RecipientType.TO, to)
    message.setSubject(subj)
    message.setText(msg)
    
    Transport.send(message)
  }
  
  /** Let user func to perform work with javax.mail.Session resource. */
  def withSess(func: Session => Unit){
    val sess = 
      if(StringUtils.isNotBlank(user)) Session.getDefaultInstance(props, userPassAuthenticator)
      else Session.getDefaultInstance(props)
      
    func(sess)  
  }
  
  /** Let user func to perform work with javax.mail.Transport resource. */
  def withTransport(func: Transport => Unit){
    withSess{ sess =>
      val transport = sess.getTransport
      try{ func(transport) }
      finally{ transport.close }
    }
  }
}

/** For testing only. Useful when you don't have a actual stmp host. */
class FakeEmailSender extends EmailSender("fake-host", 25, "fake-from@fake.com", false, "", ""){
  override def send(to: String, subj: String, msg: String){
    logger.info("Sending Fake Email")
    logger.debug("Fake Send email to: "+to)
    logger.debug("Fake Subj: "+subj)
    logger.debug("Fake Msg: "+msg)
  }
}

